/**
 * 上传管理器类
 * 负责处理文件上传的完整流程，包括配置验证、上传执行、重试机制、错误处理等
 */
export class UploadManager {
  constructor() {
    // 上传状态管理
    this.uploadState = {
      isUploading: false,
      currentRetry: 0,
      lastError: null,
      uploadStartTime: null,
      canRetry: true
    };
  }
 
  /**
   * 执行文件上传
   * @param {string} filePath - 文件路径
   * @param {Object} config - 上传配置
   * @returns {Promise} 上传结果
   */
  async performUpload(filePath, config) {
    if (!filePath) {
      throw new Error('文件路径不能为空');
    }
    
    if (!config || !config.uploadUrl) {
      throw new Error('上传配置或上传地址不能为空');
    }
    
    this.uploadState.isUploading = true;
    this.uploadState.error = null;
    
    try {
      const result = await this._uploadWithUni(filePath, config);
      return await this.handleUploadSuccess(result, config);
    } catch (error) {
      return await this.handleUploadError(error, filePath, config);
    }
  }
 
  /**
   * 处理上传成功
   * @param {Object} result - 上传结果
   * @param {Object} config - 上传配置
   * @returns {Object} 处理后的结果
   */
  handleUploadSuccess(result, config) {
    this.uploadState.isUploading = false;
    this.uploadState.retryCount = 0;
    
    let fileUrl = null;
    
    try {
      // 尝试解析响应数据
      const responseData = typeof result.data === 'string' ? JSON.parse(result.data) : result.data;
      
      // 提取文件URL
      fileUrl = this._extractFileUrl(responseData, config);
      
      if (!fileUrl) {
        throw new Error('无法从响应中提取文件URL');
      }
      
      return {
        success: true,
        fileUrl,
        response: responseData,
        statusCode: result.statusCode
      };
    } catch (error) {
      console.error('[UploadManager] 处理上传成功响应时出错:', error);
      throw new Error('上传成功但处理响应失败: ' + error.message);
    }
  }
 
  /**
   * 处理上传错误
   * @param {Object} error - 错误对象
   * @param {string} filePath - 文件路径
   * @param {Object} config - 上传配置
   * @returns {Object} 错误处理结果
   */
  async handleUploadError(error, filePath, config) {
    this.uploadState.isUploading = false;
    this.uploadState.error = error;
    
    // 判断是否需要重试
    if (this._shouldRetryUpload(error) && this.uploadState.retryCount < this.maxRetries) {
      return await this.handleUploadRetry(filePath, config);
    }
    
    // 重试次数用完或不需要重试，返回最终错误
    return {
      success: false,
      error: error,
      message: this._getErrorMessage(error),
      retryCount: this.uploadState.retryCount,
      canRetry: this.uploadState.retryCount < this.maxRetries
    };
  }
 
  /**
   * 处理上传重试
   * @param {string} filePath - 文件路径
   * @param {Object} config - 上传配置
   * @returns {Promise} 重试结果
   */
  async handleUploadRetry(filePath, config) {
    this.uploadState.retryCount++;
    
    // 计算重试延迟时间（指数退避）
    const delay = Math.min(1000 * Math.pow(2, this.uploadState.retryCount - 1), 10000);
    
    console.log(`[UploadManager] 第${this.uploadState.retryCount}次重试，延迟${delay}ms`);
    
    // 等待延迟时间
    await new Promise(resolve => setTimeout(resolve, delay));
    
    // 重新尝试上传
    return await this.performUpload(filePath, config);
  }
 
  /**
   * 重置上传状态
   */
  resetUploadState() {
    this.uploadState = {
      isUploading: false,
      retryCount: 0,
      error: null
    };
  }
  
  /**
   * 使用uni.uploadFile执行上传
   * @private
   * @param {string} filePath - 文件路径
   * @param {Object} config - 上传配置
   * @returns {Promise} 上传Promise
   */
  _uploadWithUni(filePath, config) {
    return new Promise((resolve, reject) => {
      const uploadOptions = {
        url: config.uploadUrl,
        filePath: filePath,
        name: config.fileName || 'file',
        timeout: config.timeout || 60000
      };
      
      // 添加表单数据
      if (config.formData && typeof config.formData === 'object') {
        uploadOptions.formData = config.formData;
      }
      
      // 添加请求头
      if (config.headers && typeof config.headers === 'object') {
        uploadOptions.header = config.headers;
      }
      
      uni.uploadFile({
        ...uploadOptions,
        success: resolve,
        fail: reject
      });
    });
  }
  
  /**
   * 从响应数据中提取文件URL
   * @private
   * @param {Object} responseData - 响应数据
   * @param {Object} config - 上传配置
   * @returns {string|null} 文件URL
   */
  _extractFileUrl(responseData, config) {
    if (!responseData) return null;
    
    // 常见的URL字段名
    const urlFields = ['url', 'fileUrl', 'file_url', 'path', 'filePath', 'file_path', 'src', 'link'];
    
    // 直接查找URL字段
    for (const field of urlFields) {
      if (responseData[field]) {
        return responseData[field];
      }
    }
    
    // 查找嵌套的data字段
    if (responseData.data) {
      for (const field of urlFields) {
        if (responseData.data[field]) {
          return responseData.data[field];
        }
      }
    }
    
    // 查找result字段
    if (responseData.result) {
      for (const field of urlFields) {
        if (responseData.result[field]) {
          return responseData.result[field];
        }
      }
    }
    
    return null;
  }
  
  /**
   * 判断是否应该重试上传
   * @private
   * @param {Object} error - 错误对象
   * @returns {boolean} 是否应该重试
   */
  _shouldRetryUpload(error) {
    if (!error) return false;
    
    const errorMsg = (error.errMsg || error.message || '').toLowerCase();
    
    // 网络相关错误可以重试
    if (errorMsg.includes('network') || errorMsg.includes('timeout') || 
        errorMsg.includes('连接') || errorMsg.includes('超时')) {
      return true;
    }
    
    // 服务器5xx错误可以重试
    if (errorMsg.includes('500') || errorMsg.includes('502') || 
        errorMsg.includes('503') || errorMsg.includes('504')) {
      return true;
    }
    
    // 其他错误不重试（如4xx客户端错误）
    return false;
  }
  
  /**
   * 获取用户友好的错误消息
   * @private
   * @param {Object} error - 错误对象
   * @returns {string} 错误消息
   */
  _getErrorMessage(error) {
    if (!error) return '上传失败';
    
    const errorMsg = (error.errMsg || error.message || '').toLowerCase();
    
    if (errorMsg.includes('network') || errorMsg.includes('连接')) {
      return '网络连接失败，请检查网络设置';
    }
    if (errorMsg.includes('timeout') || errorMsg.includes('超时')) {
      return '上传超时，请稍后重试';
    }
    if (errorMsg.includes('500')) {
      return '服务器内部错误，请稍后重试';
    }
    if (errorMsg.includes('404')) {
      return '上传地址不存在，请检查配置';
    }
    if (errorMsg.includes('403')) {
      return '没有上传权限，请联系管理员';
    }
    if (errorMsg.includes('413')) {
      return '文件过大，请选择较小的文件';
    }
    
    return error.errMsg || error.message || '上传失败，请重试';
  }
}
 
/**
 * 创建上传管理器实例
 * @returns {UploadManager} 上传管理器实例
 */
export function createUploadManager() {
  return new UploadManager();
}
 
/**
 * 默认导出上传管理器类
 */
export default UploadManager;